package com.oyjd.framework.ui.gallery;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.HashMap;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;

import com.oyjd.framework.Const;
import com.oyjd.framework.log.MyLog;
import com.oyjd.framework.util.HttpNet;

/**
 * 异步下载图片的工具类
 * 
 * @author dengweiming
 * 
 */
@SuppressLint("DefaultLocale")
public class AsyncImageLoader {
	private final static String TAG = "AsyncImageLoader";

	/** 缓存路径 */
	String mStoragePath = Const.APP_IMG_DIR;

	/**
	 * 是否强制使用png格式。 有些jpg/jpeg格式的图片使用Android的API压缩存储到sd卡 后再读取就会损失质量，使用png格式则可以无损
	 * */
	boolean mForceUsePngFormat = true;

	private HashMap<String, SoftReference<Drawable>> mImageCache;

	/**
	 * 图片装载完成的回调者
	 */
	public interface ImageCallback {
		public void imageLoaded(Drawable imageDrawable, String imageUrl);
	}

	public AsyncImageLoader() {
		mImageCache = new HashMap<String, SoftReference<Drawable>>();
	}

	/**
	 * 异步装载图片
	 * 
	 * @param imageUrl
	 * @param imageCallback
	 * @return
	 */
	@SuppressLint("HandlerLeak")
	public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
		/*
		 * 先从内存中查找，找不到则到sd卡中查找，还找不到才从网络下载，并写到内存和sd卡中。
		 */
		if (mImageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = mImageCache.get(imageUrl);
			Drawable drawable = softReference.get();
			if (drawable != null) {
				imageCallback.imageLoaded(drawable, imageUrl);
				return drawable;
			}
		}
		final Handler handler = new Handler() {
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
			}
		};
		new AsyncTask<String, String, Drawable>() {
			@Override
			protected Drawable doInBackground(String... params) {
				String imgUrl = params[0];
				String fileName = imageUrl.substring(imageUrl.lastIndexOf("/"));
				Drawable drawable = readImageFromSdCard(fileName);
				if (drawable == null) {

					Bitmap bitmap = null;
					try {
						byte[] b = HttpNet.getBytesFromNet(imgUrl);
						bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
						if (bitmap != null) {
							saveImageToSdCard(bitmap, fileName);
						}
						if (bitmap != null) {
							drawable =Drawable.createFromStream(new ByteArrayInputStream(b), "tmp");
						}
						b = null;
						bitmap = null;
					} catch (Exception e) {
						MyLog.e(TAG, e.getMessage(), e);
					}
				}
				if (drawable != null) {
					mImageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
					Message message = handler.obtainMessage(0, drawable);
					handler.sendMessage(message);
				}
				return drawable;
			}
		}.execute(imageUrl);
		return null;
	}

	/**
	 * 保存图片
	 * 
	 * @param bm
	 * @param fileName
	 * @throws IOException
	 */
	@SuppressLint("DefaultLocale")
	public void saveImageToSdCard(Bitmap bm, String fileName) {
		String state = android.os.Environment.getExternalStorageState();
		if (!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
			return;
		}
		try {
			File dirFile = new File(mStoragePath);
			if (!dirFile.exists()) {
				dirFile.mkdirs();
			}
			fileName = fileName.toLowerCase();
			if (mForceUsePngFormat) {
				fileName = fileName.replaceFirst("\\.jpg$", ".png");
				fileName = fileName.replaceFirst("\\.jpeg$", ".png");
			}
			File file = new File(mStoragePath + fileName);
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
			if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
				bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
			} else if (fileName.endsWith(".png")) {
				bm.compress(Bitmap.CompressFormat.PNG, 100, bos);
			} else {
				MyLog.w(TAG, "Not support this file type: " + fileName);
			}
			bos.flush();
			bos.close();
		} catch (Exception e) {
			e.printStackTrace();
			MyLog.w(TAG, "Failed to save file: " + fileName);
		}
	}

	/**
	 * 读取图片
	 * 
	 * @param fileName
	 * @return
	 */
	@SuppressLint("DefaultLocale")
	public Drawable readImageFromSdCard(String fileName) {
		String state = android.os.Environment.getExternalStorageState();
		if (!state.equals(android.os.Environment.MEDIA_MOUNTED) && !state.equals(android.os.Environment.MEDIA_MOUNTED_READ_ONLY)) {
			return null; // sdcard不可读
		}
		Drawable d = null;
		fileName = fileName.toLowerCase();
		if (mForceUsePngFormat) {
			fileName = fileName.replaceFirst("\\.jpg$", ".png");
			fileName = fileName.replaceFirst("\\.jpeg$", ".png");
		}
		File myFile = new File(mStoragePath + fileName);
		if (myFile.exists()) {
			try {
				FileInputStream i = new FileInputStream(myFile);
				d = Drawable.createFromStream(i, "src");
				i.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return d;
	}
}
